package com.cracker.websocket.server.service;

import com.alibaba.fastjson.JSONObject;
import com.cracker.websocket.server.constant.CmdConstant;
import com.cracker.websocket.server.constant.MessageTypeConstant;
import com.cracker.websocket.server.dao.ChatRoomDao;
import com.cracker.websocket.server.dto.ResponseCmdDto;
import com.cracker.websocket.server.dto.message.ChatRoomMessageDto;
import com.cracker.websocket.server.dto.messagemeta.AudioMessage;
import com.cracker.websocket.server.dto.messagemeta.TextMessage;
import com.cracker.websocket.server.entity.ChatRoomEntity;
import com.cracker.websocket.server.entity.UserEntity;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.websocket.Session;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 聊天室服务
 */
@Service
@Data
@Slf4j
public class ChatRoomService {
    @Autowired
    private SessionService sessionService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private ChatRoomDao chatRoomDao;
    private Map<String, Set<Integer>> userMap = new ConcurrentHashMap<>();
    private Map<String, Set<Session>> sessionMap = new ConcurrentHashMap<>();

    public Set<Integer> listUserIdByRoomId(String roomId) {
        return userMap.get(roomId);
    }

    public Set<Session> listSessionByRoomId(String roomId) {
        return sessionMap.get(roomId);
    }

    public void addUser(Session session, int userId, String roomId) {
        Set<Integer> userList = userMap.get(roomId);
        Set<Session> sessionList = sessionMap.get(roomId);
        if (null == userList) {
            userList = new LinkedHashSet<>();
        }
        if (null == sessionList) {
            sessionList = new HashSet<>();
        }
        userList.add(userId);
        sessionList.add(session);
        userMap.put(roomId, userList);
        sessionMap.put(roomId, sessionList);
    }

    public void removeUser(int userId, String roomId) {
        Set<Session> sessionList = sessionMap.get(roomId);
        Set<Integer> userList = userMap.get(roomId);
        if (null != sessionList) {
            sessionList.remove(sessionService.getByUserId(userId));
        }
        if (null != userList) {
            userList.remove(userId);
        }
        userMap.put(roomId, userList);
        sessionMap.put(roomId, sessionList);
        // TODO 通知聊天室用户下线
    }

    public void broadcast(Session session, String roomId, ChatRoomMessageDto messageDto) throws IOException {
        // 处理发送消息类型
        switch (messageDto.getMessageType()) {
            case MessageTypeConstant.TEXT:
                TextMessage textMessage = ((JSONObject) messageDto.getMessage()).toJavaObject(TextMessage.class);
                messageDto.setMessage(textMessage);
                log.warn("发送文本消息 {}", textMessage);
                break;
            case MessageTypeConstant.AUDIO:
                AudioMessage audioMessage = ((JSONObject) messageDto.getMessage()).toJavaObject(AudioMessage.class);
                messageDto.setMessage(audioMessage);
                log.warn("发送语音消息 {}", audioMessage);
                break;
        }
        listSessionByRoomId(roomId).forEach((e) -> {
            if (!e.getId().equals(session.getId())) {
                try {
                    e.getBasicRemote().sendText(messageService.encode(messageDto));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
        ResponseCmdDto<ChatRoomMessageDto> responseCmdDto = new ResponseCmdDto<>();
        responseCmdDto.setCmd(CmdConstant.CHATROOM_MSG);
        responseCmdDto.setData(messageDto);
        session.getBasicRemote().sendText(messageService.encode(responseCmdDto));
        // TODO 持久化聊天数据
    }

    /**
     * 用户进入聊天室
     */
    public void join(Session session, String roomId) {
        UserEntity userEntity = (UserEntity) session.getUserProperties().get("user");
        ChatRoomEntity chatRoomEntity = chatRoomDao.getById(roomId);
        userEntity.setChatRoomEntity(chatRoomEntity);
        addUser(session, userEntity.getId(), chatRoomEntity.getId());
        // TODO 通知聊天室用户上线
        try {
            ResponseCmdDto<Object> responseCmdDto = new ResponseCmdDto<>();
            responseCmdDto.setCmd(CmdConstant.CHATROOM_JOIN);
            session.getBasicRemote().sendText(messageService.encode(responseCmdDto));
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.warn("用户:{} 进入聊天室:{}", userEntity.getId(), roomId);
    }

    /**
     * 用户退出聊天室
     */
    public void quit(Session session, UserEntity userEntity) {
        ChatRoomEntity chatRoomEntity = userEntity.getChatRoomEntity();
        if (null != chatRoomEntity) {
            removeUser(userEntity.getId(), chatRoomEntity.getId());
            log.warn("用户:{} 退出聊天室:{}", userEntity.getId(), chatRoomEntity.getId());
        }
    }
}
